home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / PaintEvent.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  7KB  |  279 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com)            | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <X11/IntrinsicP.h>
  16. #include "PaintP.h"
  17. #include "xpaint.h"
  18.  
  19. typedef void    (*func_t)(Widget, void *, XEvent *, OpInfo *);
  20.  
  21. typedef struct data_s {
  22.     Widget        w;
  23.     func_t        func;
  24.         void            *data;
  25.         int             mask, flag;
  26.     int        surfMask;
  27.         struct data_s   *next;
  28.     OpInfo        *info;
  29. } data_t;
  30.  
  31. static data_t    *list = NULL;
  32.  
  33. #if 0
  34. static data_t    **widgetEvent(Widget w, data_t *look)
  35. {
  36.     static data_t    *d[10];
  37.     data_t        *cur = list;
  38.     int        n = 0;
  39.  
  40.     while (cur != NULL) {
  41.         if (cur->mask == look->mask &&
  42.             cur->flag == look->flag &&
  43.             cur->func == look->func &&
  44.             cur->w    == w) 
  45.             d[n++] = cur;
  46.         cur = cur->next;
  47.     }
  48.  
  49.     d[n] = NULL;
  50.  
  51.     return n == 0 ? NULL : d;
  52. }
  53. #endif
  54.  
  55. static void opHandleEvent(Widget w, XtPointer dataArg, XEvent *event, Boolean *junk)
  56. {
  57.     data_t        *data = (data_t*)dataArg;
  58.     int        snap;
  59.     PaintWidget    paint = (PaintWidget)w;
  60.     OpInfo        *info = data->info;
  61.     static Window    lastWindow  = None;
  62.     static Display    *lastDisplay = None;
  63.     static int    lastType;
  64.     static int    lastX, lastY;
  65.     Boolean        same;
  66.     int        zoom;
  67.  
  68. #if 0
  69.     XEvent        myEvent;
  70.  
  71.     memcpy(&myEvent, event, sizeof(XEvent));
  72.     event = &myEvent;
  73. #endif
  74.  
  75.     /*
  76.     **  Figure out if there is a snap, either by
  77.     **   choice or by zooming
  78.     */
  79.     if ((info->zoom = GET_ZOOM(paint)) == 0)
  80.         info->zoom = 1;
  81.     if (info->isFat = ((zoom = GET_ZOOM(paint)) > 1))
  82.         snap = GET_ZOOM(paint);
  83.     else if (paint->paint.snapOn)
  84.         snap = paint->paint.snap;
  85.     else
  86.         snap = 1;
  87.  
  88.     same = (event->xany.window == lastWindow) && 
  89.            (event->xany.display == lastDisplay) && 
  90.                (event->xany.type == lastType);
  91.     lastWindow  = event->xany.window;
  92.     lastDisplay = event->xany.display;
  93.     lastType    = event->xany.type;
  94.  
  95.     /*
  96.     **  Snap events to the snap
  97.     */
  98.     if (event->type == ButtonPress || event->type == ButtonRelease) {
  99.         info->realX = event->xbutton.x;
  100.         info->realY = event->xbutton.y;
  101.     } else if (event->type == MotionNotify) {
  102.         info->realX = event->xmotion.x;
  103.         info->realY = event->xmotion.y;
  104.     }
  105.  
  106.     if (((event->type == ButtonPress) ||
  107.          (event->type == ButtonRelease) ||
  108.          (event->type == MotionNotify)) && snap > 1) {
  109.         switch (event->type) {
  110.         case ButtonPress:
  111.         case ButtonRelease:
  112.             event->xbutton.x = event->xbutton.x - 
  113.                         (event->xbutton.x % snap);
  114.             event->xbutton.y = event->xbutton.y - 
  115.                         (event->xbutton.y % snap);
  116.             if (same && lastX == event->xbutton.x && lastY == event->xbutton.y)
  117.                 return;
  118.             break;
  119.         case MotionNotify:
  120.             event->xmotion.x = event->xmotion.x - 
  121.                         (event->xmotion.x % snap);
  122.             event->xmotion.y = event->xmotion.y - 
  123.                         (event->xmotion.y % snap);
  124.             if (same && lastX == event->xmotion.x && lastY == event->xmotion.y)
  125.                 return;
  126.             break;
  127.         }
  128.         lastX = event->xmotion.x;
  129.         lastY = event->xmotion.y;
  130.     } else {
  131.         lastX = lastY = -1;
  132.     }
  133.  
  134.     if (event->type == MotionNotify) {
  135.         info->x = (event->xmotion.x / zoom) + paint->paint.zoomX;
  136.         info->y = (event->xmotion.y / zoom) + paint->paint.zoomY;
  137.     } else if (event->type == ButtonPress || event->type == ButtonRelease) {
  138.         info->x = (event->xbutton.x / zoom) + paint->paint.zoomX;
  139.         info->y = (event->xbutton.y / zoom) + paint->paint.zoomY;
  140.     }
  141.     /*
  142.     **  In fatbits we can't tell the difference 
  143.     **   between snaping an fat bits.
  144.     */
  145.     if (info->isFat) {
  146.         info->realX = info->x;
  147.         info->realY = info->y;
  148.     } else {
  149.         info->realX = info->realX + paint->paint.zoomX;
  150.         info->realY = info->realY + paint->paint.zoomY;
  151.     }
  152.  
  153.     /*
  154.     **  If this is button down, save it for reference
  155.     */
  156.     if (event->type == ButtonPress) {
  157.         paint->paint.downX = info->realX;
  158.         paint->paint.downY = info->realY;
  159.     }
  160.  
  161.     if (paint->paint.paint != None) {
  162.         PaintWidget    pw = (PaintWidget)paint->paint.paint;
  163.         info->base = pw->paint.sourcePixmap;
  164.     } else {
  165.         info->base = paint->paint.sourcePixmap;
  166.     }
  167.  
  168.     if (data->surfMask & opWindow) {
  169.         int    z = GET_ZOOM(paint) / 2;
  170.  
  171.         if (z != 0) {
  172.             if (event->type == MotionNotify) {
  173.                 event->xmotion.x += z;
  174.                 event->xmotion.y += z;
  175.             } else if (event->type == ButtonPress || event->type == ButtonRelease) {
  176.                 event->xbutton.x += z;
  177.                 event->xbutton.y += z;
  178.             }
  179.         }
  180.  
  181.         info->surface  = opWindow;
  182.         info->drawable = event->xany.window;
  183.         data->func(w, data->data, event, info);
  184.     }
  185.     if (event->type == MotionNotify) {
  186.         event->xmotion.x = info->x;
  187.         event->xmotion.y = info->y;
  188.     } else if (event->type == ButtonPress || event->type == ButtonRelease) {
  189.         event->xbutton.x = info->x;
  190.         event->xbutton.y = info->y;
  191.     }
  192.  
  193.     if (data->surfMask & opPixmap) {
  194.         info->surface = opPixmap;
  195.         info->drawable = GET_PIXMAP(paint);
  196.         data->func(w, data->data, event, info);
  197.     }
  198. }
  199.  
  200. void OpAddEventHandler(Widget w, int surfMask, int mask, Boolean flag, 
  201.         void (*func)(Widget,void *, XEvent*, OpInfo *), void *data)
  202. {
  203.     PaintWidget    paint = (PaintWidget)w;
  204.     PaintWidget    pp    = (PaintWidget)paint->paint.paint;
  205.     data_t        *new = (data_t *)XtMalloc(sizeof(data_t));
  206.     OpInfo        *info;
  207.  
  208.     if (new == NULL)
  209.         return;
  210.  
  211.     new->w        = w;
  212.     new->func     = func;
  213.     new->data     = data;
  214.     new->mask     = mask;
  215.     new->flag     = flag;
  216.     new->surfMask = surfMask;
  217.  
  218.     info = new->info = (OpInfo*)XtMalloc(sizeof(OpInfo));
  219.     info->refCount = 1;
  220.     info->realX = 0;
  221.     info->realY = 0;
  222.  
  223.     /*
  224.     **  Now build the approprate info structure
  225.     */
  226.     if (pp == None) {
  227.         /*
  228.         ** If this is a paint widget, this is easy
  229.         */
  230.         info->first_gc  = paint->paint.fgc;
  231.         info->second_gc = paint->paint.sgc;
  232.         info->base_gc   = paint->paint.igc;
  233.     } else {
  234.         /*
  235.         ** For a fatbits paint widget get paint information
  236.         */
  237.         info->first_gc  = pp->paint.fgc;
  238.         info->second_gc = pp->paint.sgc;
  239.         info->base_gc   = pp->paint.igc;
  240.     }
  241.  
  242.     new->next = list;
  243.     list      = new;
  244.  
  245.         XtAddEventHandler(w, mask, flag, opHandleEvent, (XtPointer)new);
  246. }
  247.  
  248. void OpRemoveEventHandler(Widget w, int surfMask, int mask, Boolean flag, 
  249.         void (*func)(Widget, void *, XEvent*, OpInfo *), void *data)
  250. {
  251.     data_t    *cur   = list;
  252.     data_t    **prev = &list;
  253.  
  254.     while (cur != NULL) {
  255.         if (cur->w        == w    &&
  256.             cur->data     == data &&
  257.             cur->mask     == mask &&
  258.             cur->flag     == flag &&
  259.             cur->surfMask == surfMask &&
  260.             cur->func     == func)
  261.             break;
  262.         prev = &cur->next;
  263.         cur = cur->next;
  264.     }
  265.  
  266.     if (cur == NULL)
  267.         return;
  268.  
  269.         XtRemoveEventHandler(w, mask, flag, opHandleEvent, (XtPointer)cur);
  270.  
  271.     *prev = cur->next;
  272.  
  273.     cur->info->refCount--;
  274.     if (cur->info->refCount == 0)
  275.         XtFree((XtPointer)cur->info);
  276.  
  277.     XtFree((XtPointer)cur);
  278. }
  279.